package cn.schoolwow.quickflow.service.quickFlow.execute;

import cn.schoolwow.quickflow.QuickFlow;
import cn.schoolwow.quickflow.QuickFlowBuilder;
import cn.schoolwow.quickflow.QuickFlowExecutor;
import cn.schoolwow.quickflow.domain.*;
import cn.schoolwow.quickflow.dto.FlowContextDataRange;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import cn.schoolwow.quickflow.flow.CompositeBusinessFlow;
import cn.schoolwow.quickflow.listener.SingleFlowListener;
import cn.schoolwow.quickflow.listener.TryCatchFinallyHandler;
import cn.schoolwow.quickflow.util.QuickFlowConfigUtil;
import cn.schoolwow.quickflow.util.QuickFlowUtil;
import com.alibaba.fastjson.JSONObject;

import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

public class QuickFlowExecuteOperationImpl implements QuickFlowExecuteOperation {
    /**流程配置信息*/
    private FlowConfig flowConfig;

    public QuickFlowExecuteOperationImpl(FlowConfig flowConfig) {
        this.flowConfig = flowConfig;
    }

    /**
     * 构建流程
     * */
    @Override
    public QuickFlowExecutor startFlow(String name) {
        if(null==name||name.isEmpty()){
            throw new IllegalArgumentException("请指定主流程名称!");
        }
        FlowExecutorConfig flowExecutorConfig = new FlowExecutorConfig();
        flowExecutorConfig.name = name;
        flowExecutorConfig.flowContext = QuickFlowUtil.getFlowContextInvocationHandler(flowExecutorConfig);
        flowExecutorConfig.currentCompositeFlowDataMap = new ConcurrentHashMap<>();
        if(null!=flowExecutorConfig.parentFlowExecutorConfig){
            flowExecutorConfig.currentCompositeFlowDataMap.putAll(flowExecutorConfig.parentFlowExecutorConfig.currentCompositeFlowDataMap);
        }

        FlowExecutorRootConfig flowExecutorRootConfig = new FlowExecutorRootConfig();
        flowExecutorRootConfig.id = System.nanoTime();
        flowExecutorRootConfig.threadLocalDataMap.set(new HashMap<>());
        flowExecutorRootConfig.flowConfig = flowConfig;
        flowExecutorRootConfig.quickFlow = flowConfig.quickFlow;
        flowExecutorConfig.flowExecutorRootConfig = flowExecutorRootConfig;

        return QuickFlowUtil.getQuickFlowExecutorInvocationHandler(flowExecutorConfig);
    }

    /**
     * 构建流程
     * */
    @Override
    public QuickFlowExecutor startFlow(BusinessFlow businessFlow) {
        return startFlow(businessFlow.name())
                .next(businessFlow);
    }

    /**
     * 构建流程
     * */
    @Override
    public QuickFlowExecutor startFlow(FlowExecutorOption flowExecutorOption) {
        if(null==flowConfig.flowConfigHandlerContext.flowMappingHandler){
            throw new IllegalArgumentException("请先指定流程名称实例映射处理器!");
        }
        if(null==flowExecutorOption.name||flowExecutorOption.name.isEmpty()){
            throw new IllegalArgumentException("请先指定流程名称!");
        }
        //首先查找复合流程
        {
            CompositeBusinessFlow compositeBusinessFlow = flowConfig.flowConfigHandlerContext.flowMappingHandler.getCompositeBusinessFlow(flowExecutorOption.name);
            if(null!=compositeBusinessFlow){
                return startFlow(compositeBusinessFlow)
                        .putFlowContextDataMap(flowExecutorOption.requestData, FlowContextDataRange.Flow);
            }
        }
        //其次查找单个流程
        {
            BusinessFlow businessFlow = flowConfig.flowConfigHandlerContext.flowMappingHandler.getFlow(flowExecutorOption.name);
            if(null!=businessFlow){
                return startFlow(businessFlow)
                        .putFlowContextDataMap(flowExecutorOption.requestData, FlowContextDataRange.Flow);
            }
        }
        //剩下为自定义流程
        if(null==flowExecutorOption.flowArray||flowExecutorOption.flowArray.isEmpty()){
            throw new IllegalArgumentException("请指定流程列表!");
        }
        QuickFlowExecutor quickFlowExecutor = startFlow(flowExecutorOption.name)
                .putFlowContextDataMap(flowExecutorOption.requestData, FlowContextDataRange.Flow);
        for(int i=0;i<flowExecutorOption.flowArray.size();i++){
            JSONObject flow = flowExecutorOption.flowArray.getJSONObject(i);
            String type = flow.getString("类型");
            String name = flow.getString("名称");
            switch (type){
                case "普通流程":{
                    if(name.startsWith("[复合流程]")){
                        String compositeBusinessName = name.substring("[复合流程]".length());
                        CompositeBusinessFlow compositeBusinessFlow = flowConfig.flowConfigHandlerContext.flowMappingHandler.getCompositeBusinessFlow(compositeBusinessName);
                        if(null==compositeBusinessFlow){
                            throw new IllegalArgumentException("复合流程不存在!流程名称:"+compositeBusinessName);
                        }
                        quickFlowExecutor.next(compositeBusinessFlow);
                    }else{
                        BusinessFlow businessFlow = flowConfig.flowConfigHandlerContext.flowMappingHandler.getFlow(name);
                        if(null==businessFlow){
                            throw new IllegalArgumentException("流程不存在!流程名称:"+name);
                        }
                        quickFlowExecutor.next(businessFlow);
                    }
                }break;
                case "处理器":{
                    String handleType = flow.getString("处理器类型");
                    switch (handleType){
                        case "TryCatchFinally":{
                            TryCatchFinallyHandler tryCatchFinallyHandler = flowConfig.flowConfigHandlerContext.flowMappingHandler.getTryCatchFinallyHandler(name);
                            if(null==tryCatchFinallyHandler){
                                throw new IllegalArgumentException("不存在TryCatchFinally处理器!处理器名称:"+name);
                            }
                            quickFlowExecutor.tryCatchFinallyHandler(tryCatchFinallyHandler);
                        }break;
                        case "SingleFlow":{
                            SingleFlowListener singleFlowListener = flowConfig.flowConfigHandlerContext.flowMappingHandler.getSingleFlowListener(name);
                            if(null==singleFlowListener){
                                throw new IllegalArgumentException("不存在singleFlow处理器!处理器名称:"+name);
                            }
                            quickFlowExecutor.singleFlowListener(singleFlowListener);
                        }break;
                        default:{
                            throw new IllegalArgumentException("不支持的处理器类型!类型"+handleType);
                        }
                    }
                }break;
                default:{
                    throw new IllegalArgumentException("不支持的流程类型!类型"+type);
                }
            }
        }
        return quickFlowExecutor;
    }

    /**
     * 构建流程
     * */
    @Override
    public QuickFlowExecutor startFlow(CompositeBusinessFlow compositeBusinessFlow) {
        QuickFlowExecutor quickFlowExecutor = startFlow(compositeBusinessFlow.name());
        compositeBusinessFlow.executeCompositeBusiness(quickFlowExecutor);

        FlowExecutorConfig flowExecutorConfig = quickFlowExecutor.getFlowExecutorConfig();
        QuickFlowConfigUtil.handleHasFlowConfig(compositeBusinessFlow, flowExecutorConfig);
        QuickFlowConfigUtil.handleLoadFlowConfig(compositeBusinessFlow, flowExecutorConfig);
        return quickFlowExecutor;
    }

    /**
     * 执行流程
     * */
    @Override
    public FlowContext executeFlow(BusinessFlow... businessFlowList) {
        BusinessFlow firstBusinessFlow = businessFlowList[0];
        QuickFlowExecutor quickFlowExecutor = startFlow(firstBusinessFlow.name());
        for(BusinessFlow businessFlow:businessFlowList){
            quickFlowExecutor.next(businessFlow);
        }
        return quickFlowExecutor.execute();
    }

    /**
     * 执行流程
     * */
    @Override
    public FlowContext executeFlow(CompositeBusinessFlow compositeBusinessFlow) {
        return startFlow(compositeBusinessFlow).execute();
    }

    /**
     * 执行流程
     * */
    @Override
    public FlowContext executeFlow(FlowExecutorOption flowExecutorOption) {
        return startFlow(flowExecutorOption).execute();
    }

    /**
     * 克隆流程对象
     * */
    @Override
    public QuickFlow cloneFlow(){
        return QuickFlowBuilder.newInstance()
                .putContextTemporaryDataMap(flowConfig.flowConfigDataContext.dataMap)
                .tryCatchFinallyHandler(flowConfig.flowConfigHandlerContext.tryCatchFinallyHandler)
                .singleFlowListener(flowConfig.flowConfigHandlerContext.singleFlowListener);
    }
}
